// 给定一个字符串 s ，请你找出其中不含有重复字符的 最长 子串 的长度。

// 示例 1:
// 输入: s = "abcabcbb"
// 输出: 3 
// 解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。

// 示例 2:
// 输入: s = "bbbbb"
// 输出: 1
// 解释: 因为无重复字符的最长子串是 "b"，所以其长度为 1。

// 示例 3:
// 输入: s = "pwwkew"
// 输出: 3
// 解释: 因为无重复字符的最长子串是 "wke"，所以其长度为 3。
//      请注意，你的答案必须是 子串 的长度，"pwke" 是一个子序列，不是子串。
 
// 提示：
// 0 <= s.length <= 5 * 104
// s 由英文字母、数字、符号和空格组成

function lengthOfLongestSubstring(s) {
  // 用 map 存储字符和索引的映射，key 为字符，value 为索引
  const map = new Map();
  // max 存储无重复字符的最长子串的长度，left 存储当前无重复字符子串的左边界
  let max = 0, left = 0;
  // 遍历字符串 s, r 为右指针
  for (let r = 0; r < s.length; r++) {
    // 如果 map 中存在 s[r]，则说明当前字符重复了
    if (map.has(s[r])) {
      // 更新左边界为重复字符的下一个位置
      left = Math.max(left, map.get(s[r]) + 1);
    }
    // 更新 map 中 s[r] 的索引为 r
    map.set(s[r], r);
    // 更新 max 为当前无重复字符子串的长度
    max = Math.max(max, r - left + 1);
  }

  return max;
}